import pandas as pd
import lightgbm as lgb
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score
import matplotlib.pyplot as plt
import joblib  # 用于导出模型
import numpy as np
from lightgbm import log_evaluation, early_stopping

import logging


def rmse(y_true, y_pred):
    """
    计算 RMSE
    :param y_true: 真实值，数组或列表
    :param y_pred: 预测值，数组或列表
    :return: RMSE 值
    """
    return np.sqrt(np.mean((np.array(y_true) - np.array(y_pred)) ** 2))

logging.info("LightGBM 模型预测开始")
# 生成示例数据
data = {
    'date_id': pd.date_range(start='2023-01-01', periods=100, freq='D'),
    'sales': np.random.randint(100, 500, size=100)  # 随机生成100天的销量数据
}
print(data)

df = pd.DataFrame(data)
df.set_index('date_id', inplace=True)

# 添加时间特征
df['day_of_week'] = df.index.dayofweek
df['day_of_month'] = df.index.day
df['month'] = df.index.month

# 特征和目标变量
X = df[['day_of_week', 'day_of_month', 'month']]
y = df['sales']

# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 创建 LightGBM 数据集
train_data = lgb.Dataset(X_train, label=y_train)
test_data = lgb.Dataset(X_test, label=y_test, reference=train_data)

# 定义 LightGBM 参数
params = {
    'objective': 'regression',  # 回归任务
    'metric': 'rmse',           # 评估指标为均方根误差
    'boosting_type': 'gbdt',    # 使用 GBDT 算法
    'num_leaves': 31,           # 叶子节点数
    'learning_rate': 0.05,      # 学习率
    'feature_fraction': 0.9,    # 特征采样比例
    'bagging_fraction': 0.8,    # 数据采样比例
    'bagging_freq': 5,          # 每 5 次迭代进行一次 bagging
    'verbose': -1               # 不输出日志
}

callbacks = [log_evaluation(period=100), early_stopping(stopping_rounds=30)]

# 训练模型
model = lgb.train(
    params,
    train_data,
    num_boost_round=100,        # 迭代次数
    valid_sets=[test_data],
    callbacks = callbacks
    # ,      # 验证集
    # early_stopping_rounds=10    # 早停轮数
)

# 导出模型到文件
model_filename = '../lightgbm_model.pkl'
joblib.dump(model, model_filename)
print(f"模型已导出到文件：{model_filename}")


# 预测测试集
y_pred = model.predict(X_test, num_iteration=model.best_iteration)

# 评估模型
mse = mean_squared_error(y_test, y_pred)
# mae = mean_absolute_error(y_test, y_pred)
r2 = r2_score(y_test, y_pred)
print(f"均方误差（MSE）：{mse}")
# print(f"R2 分数：{r2}")
print("RMSE:", rmse(y_test, y_pred))

print(f'Mean Squared Error: {mse}')

# 生成未来7天的日期
future_dates = pd.date_range(start='2023-04-11', periods=7, freq='D')

# 创建未来7天的特征
future_df = pd.DataFrame({
    'date_id': future_dates,
    'day_of_week': future_dates.dayofweek,
    'day_of_month': future_dates.day,
    'month': future_dates.month
})

# 预测未来7天的销量
future_sales = model.predict(future_df[['day_of_week', 'day_of_month', 'month']], num_iteration=model.best_iteration)

# 将预测结果添加到 DataFrame
future_df['predicted_sales'] = future_sales

# 查看预测结果
print(future_df[['date_id', 'predicted_sales']])



# 可视化历史数据和预测结果
plt.figure(figsize=(12, 6))
plt.plot(df.index, df['sales'], label='Historical Sales')
plt.plot(future_df['date_id'], future_df['predicted_sales'], label='Predicted Sales', linestyle='--', marker='o')
plt.xlabel('date_id')
plt.ylabel('Sales')
plt.title('Historical and Predicted Sales (LightGBM)')
plt.legend()
plt.show()
logging.info("LightGBM 模型预测开始")

